package com.spzx.payment.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.order.api.RemoteOrderService;
import com.spzx.order.api.domain.OrderInfo;
import com.spzx.order.api.domain.OrderItem;
import com.spzx.payment.domain.PaymentInfo;
import com.spzx.payment.mapper.PaymentInfoMapper;
import com.spzx.payment.service.IPaymentInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 付款信息表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-12-30
 */
@Service
public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfo> implements IPaymentInfoService {

    @Autowired
    private RemoteOrderService orderService;

    /**
     * 根据订单号，获取支付信息，并且保存支付信息到数据库
     * @param orderNo
     * @return
     */
    @Override
    public PaymentInfo savePaymentInfo(String orderNo) {
        /**
         * 1.防止重复提交支付信息
         *   因为我们的业务流程中，用户发起支付请求的时候，我们会将当前的订单号传到支付模块下
         *   然后将订单号交给当前方法，我们会将订单信息，包括订单号存入我们的payment_info表中
         *   所以为了防止【重复提交】，在进行该方法前，我们要先去数据库表中查询是否存在该订单号
         *   若存在，则直接返回，若不存在，那么就说明当前订单是第一次提交到支付模块，那么就进行保存
         */
        PaymentInfo existPaymentInfo = baseMapper.selectOne(
                new LambdaQueryWrapper<PaymentInfo>().eq(PaymentInfo::getOrderNo, orderNo)
        );
        //若当前查询到的数据不为空，则说明当前订单已经存在，直接将当前订单数据返回
        if(existPaymentInfo != null) {
            return existPaymentInfo;
        }

        //2.调用远程模块，根据订单号获取订单详情数据，然后组装订单信息对象
        R<OrderInfo> orderInfoResult = orderService.getByOrderNo(orderNo, SecurityConstants.INNER);
        if (R.FAIL == orderInfoResult.getCode()) {
            throw new ServiceException(orderInfoResult.getMsg());
        }
        OrderInfo orderInfo = orderInfoResult.getData();
        //orderInfo当中有orderItemList属性，我们通过这个属性来获取订单的货物名字信息，然后组装content属性
        //通过流式操作orderItemList，获取所有的skuName属性然后通过join方法，将所有的skuName属性拼接成一个字符串
        String content = orderInfo.getOrderItemList()
                .stream()
                .map(OrderItem::getSkuName)
                .collect(Collectors.joining("  "));

        //3.组装PaymentInfo对象
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setUserId(SecurityUtils.getUserId());
        paymentInfo.setOrderNo(orderNo);
        paymentInfo.setAmount(orderInfo.getTotalAmount());
        paymentInfo.setContent(content);
        paymentInfo.setPaymentStatus("0");
        //4.将当前的PaymentInfo对象保存到数据库中
        baseMapper.insert(paymentInfo);

        //5.将数据返回
        return paymentInfo;
    }

    /**
     * 确认用户支付成功
     * 修改支付信息表中的信息
     * @param paramMap
     * @param payType
     */
    @Override
    public void updatePaymentStatus(Map<String, String> paramMap, int payType) {
        //若当前订单信息的状态已经是已付款，那么就直接返回，避免重复提交
        String orderNo = paramMap.get("out_trade_no");
        PaymentInfo paymentInfo = baseMapper.selectOne(new LambdaQueryWrapper<PaymentInfo>()
                .eq(PaymentInfo::getOrderNo, orderNo));
        if ("1".equals(paymentInfo.getPaymentStatus())){
            return;
        }

        //更新支付信息
        paymentInfo.setPayType(payType);
        paymentInfo.setPaymentStatus("1");
        paymentInfo.setTradeNo(paramMap.get("trade_no"));
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setCallbackContent(JSON.toJSONString(paramMap));
        baseMapper.updateById(paymentInfo);
    }
}
